/**
 * 65c816.h
 * Defines the functionality of the SNES CPU.
 *
 * @author  Philippe Johnson
 */

#ifndef __65C816_H__
#define __65C816_H__

#include "common.h"
#include "snes.h"
#include "memory.h"
#include "opcodetables.h"

#define CFLAGMASK       ( 1 )
#define ZFLAGMASK       ( 1 << 1 )
#define IFLAGMASK       ( 1 << 2 )
#define DFLAGMASK       ( 1 << 3 )
#define XFLAGMASK       ( 1 << 4 )
#define MFLAGMASK       ( 1 << 5 )
#define VFLAGMASK       ( 1 << 6 )
#define NFLAGMASK       ( 1 << 7 )

#define COPVECTOR       (0xFFE8)
#define BRKVECTOR       (0xFFE6)
#define ABTVECTOR       (0xFFE8)
#define NMIVECTOR       (0xFFEA)
#define RSTVECTOR       (0xFFFC)
#define IRQVECTOR       (0xFFEE)

typedef struct __CPUContext {
    u16 resetVector;
    u16 breakVector;
    u16 nmiVector;
    u16 copVector;
    union {           /* Accumulator */
        struct {
            u8 al;    /* Low half of accumulator  */
            u8 ah;    /* High half of accumulator */
        };
        u16 ac;       /* Entire 16-bit accumulator */
    } A;
    union {           /* X index register */
        struct {
            u8 xl;
            u8 xh;
        };
        u16 x;
    } X;
    union {           /* Y index register */
        struct {
            u8 yl;
            u8 yh;
        };
        u16 y;
    } Y;
    union {           /* Program counter */
        struct {
            u16 PCL;  /* Program counter (low word) */
            u8  PBR;  /* Program bank register      */
        };
        u32 PCR;      /* Full program counter       */
    } PC;

    u16 DPR;          /* Direct page register       */
    u16 SP;           /* Stack pointer              */
    u8  DBR;          /* Data bank register         */
    u8  P;            /* Process status register    */

    u8  emuFlag;      /* Emulation flag bit         */
    u8  carryFlag;    /* Represents P carry bit     */
    u8  zeroFlag;     /* Represents P zero bit      */
    u8  irqFlag;      /* Represents P idisable bit  */
    u8  overflowFlag; /* Represents P overflow bit  */
    u8  negativeFlag; /* Represents P negative bit  */
    u8  mFlag;        /* Represents P M flag bit    */
    u8  xFlag;        /* Represents P X flag bit    */

    s32 cycleCounter; /* Number of cycles to execute */
} CPUContext;

#define OPCODEHASH(opCode)      ((opCode << 2) | (CPU.mFlag << 1) | (CPU.xFlag))

extern CPUContext CPU;

/**
 * initializeCPU
 * Initializes the CPU, sets the vectors, PC, etc.
 *
 * @param info Information about this ROM taken from the "cartridge"
 */
void initializeCPU( CartridgeInfo* info );

/**
 * cpuExecute
 * Executes a certain number of cycles and adjusts the master clock 
 * counter appropriately.
 *
 * @param cycles The number of cycles to execute
 * @return The number of cycles actually executed
 */
unsigned int cpuExecute( u32 cycles );

#endif /* __65C816_H__ */
